#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <dirent.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 
#include <limits.h> /* limits.h defines "PATH_MAX". */ 
#include <sys/stat.h> 
int o_dir(char * dir, int level, char * f_name); 
void get_permissions (char *mode, unsigned int imode);
int main( int argc, char *argv[] ) 
{     
  char d_name[3] = ".";     /* initial directory */      //Debug - cleaner way of formatting pointers?       
  char * p_name = d_name;     
  char * pf_name = NULL;       //Obtain Argument     
if ( argc == 2 ) /* argc should be 2 for correct execution */    
{         //printf( "Argument is %s\n", argv[1] );     
  pf_name = argv[1];     //strcpy(f_name, argv[1]);     
}     // Error Checking for > 1 Argument     
if ( argc > 2 )     
{     
  printf( "Usage: %s (optional)filename\nExiting.\n", argv[0] );     
  return -1;     
}         
o_dir(p_name, 0, pf_name);     
return EXIT_SUCCESS; 
}
int o_dir( char * c_dir, int level, char * f_name ) 
{     
  DIR * dir = opendir(c_dir);     
  struct dirent * file;     
  while ( ( file = readdir( dir ) ) != NULL )     
  {     // check for dir open failure     
    if ( dir == NULL )     
    {         
      perror( "opendir() failed\n" );         
      return EXIT_FAILURE;     
    }     // Read File Info         
    struct stat buf;         
    int rc = lstat( file->d_name, &buf );     // check for . or .. as first char in name       
    if ( (strcmp (file->d_name, "..") != 0 && strcmp (file->d_name, ".") != 0) && ( S_ISDIR(buf.st_mode) || ( S_ISREG( buf.st_mode ) && (f_name == NULL || strcmp(f_name, file->d_name) == 0))))     
    {         //Print Directory Level Spacing         
      int i;         
      for(i=0; i<level*4;i++)         
      printf(" ");           //@DEBUG - What is this used for?         
      if ( rc < 0 )         
      {              /* perror( "lstat() failed\n" );  */         /* return EXIT_FAILURE;  */       
      }         
      else        
      {         
      printf( "%s ", file->d_name);         
        if ( S_ISDIR( buf.st_mode ) )         
	{               
	  char rwx_perms[12];             
	  get_permissions (rwx_perms, buf.st_mode);             
	  printf( "(subdirectory) [%s]\n",  rwx_perms);             // Recursive Section             
	  int path_length;             
	  char path[PATH_MAX];             
	  path_length = snprintf (path, PATH_MAX, "%s/%s", c_dir, file->d_name);             //Check Path Length             
	  if (path_length >= PATH_MAX)             
	  {                 
	    fprintf (stderr, "Path length has got too long.\n");                 
	    exit (EXIT_FAILURE);             
	  }             //Recursively call with the new path.             
	  chdir(file->d_name);             
	  o_dir (".", level + 1, f_name);             
	  chdir("..");         
	}         // Regular File         
	else if ( S_ISREG(buf.st_mode) )         
	{             //Determine rwx_perms             
	  char rwx_perms[12];             
	  get_permissions (rwx_perms, buf.st_mode);             
	  printf( "(%d bytes) [%s]\n", (int) buf.st_size, rwx_perms);         
	}         // Sub-Directory         // System Link         /*else if ( S_ISLNK( buf.st_mode ) )         {             printf( "[symbolic link]\n" );             }*/        // Unknown File         /* else */        /* { */        /*     //Do Nothing */        /* } */        
}     
      }     
    }     
    closedir( dir );     
    return EXIT_SUCCESS; 
} 
void get_permissions (char *mode, unsigned int imode ) 
{     int i[16];     int count=0;     int rem;     memset( i,0,16 );     memset( mode,'\0',11 );       /*Convert to binary*/    
while ( imode>0 )     
{     rem=imode%2;     imode/=2;     i[count]=rem;     count++;     }     /*End Binary Coversion*/    
count=0;       /*Start Processing bits*/    
int j;     
for ( j=15;j>=0;j-- )     
{     
switch ( j )     
{     
case 15 :   
if ( i[j]==1 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='d';         count++;         }         
break;     
case  8 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='r';         count++;         }         
break;     
case  7 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='w';         count++;         }         
break;     
case  6 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='x';         count++;         }         
break;     
case  5 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='r';         count++;         }         
break;     
case  4 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='w';         count++;         }         
break;     
case  3 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='x';         count++;         }         
break;     
case  2 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='r';         count++;         }         
break;     
case  1 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='w';         count++;         }         
break;     
case  0 :   
if ( i[j]==0 )         
{         mode[count]='-';         count++;         } 
else 
{         mode[count]='x';         count++;         }         
break;     
}     
} 
}
